package com.yunfei.commonbase.base;

import com.yunfei.commonbase.annotation.Id;
import com.yunfei.commonbase.annotation.Table;
import com.yunfei.commonbase.base.entity.Example;
import com.yunfei.commonbase.generationcode.code.CreateCode;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import static com.yunfei.commonbase.generationcode.code.CreateCode.camelToUnderline;

public class SqlProvider {
    private static final Logger logger = LoggerFactory.getLogger(SqlProvider.class);

    public String getListByExample(Example example,int pageNum ,int pageSize) throws Exception {
        Class beanClass = example.getRelation();
        String tableName = getTableName(beanClass);
        Field[] fields = getFields(beanClass);
        StringBuilder selectSql = new StringBuilder();
        selectSql.append("select ");
        try {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                Ignore ignore = field.getAnnotation(Ignore.class);
                if (ignore != null) {
                    continue;
                }
                String columnName = CreateCode.camelToUnderline(field.getName());
                if (i != 0) {
                    selectSql.append(",");
                }
                selectSql.append(columnName).append(" ").append(CreateCode.camelCase(columnName));

            }
        } catch (Exception e) {
            throw new RuntimeException("getListByEntity sql is exceptoin:" + e);
        }
        selectSql.append(" from ").append(tableName);
        if (StringUtils.isNotEmpty(example.getCondition())) {
            selectSql.append(" where").append(example.getCondition());
        }
        if (StringUtils.isNotEmpty(example.getOrderBy())) {
            selectSql.append(" order by ").append(example.getOrderBy());
        }
        if(pageNum!=0&&pageSize!=0){
            selectSql.append(" limit ").append((pageNum-1)*pageSize).append(",").append(pageSize);
        }
        System.out.println(selectSql);
        return selectSql.toString();
    }

    public String deleteByEntity(Object bean) throws Exception {
        Class<?> beanClass = bean.getClass();
        String tableName = getTableName(beanClass);
        Field[] fields = getFields(beanClass);
        StringBuilder deleteSql = new StringBuilder();
        deleteSql.append(" delete from ").append(tableName).append(" where  ");
        try {
            boolean check = false;
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                if (field.getAnnotation(Ignore.class) != null) {
                    continue;
                }
                String columnName;
                columnName = CreateCode.camelToUnderline(field.getName());
                field.setAccessible(true);
                Object beanValue = field.get(bean);
                if (beanValue != null) {
                    if (check) {
                        deleteSql.append(" and ");
                    }
                    deleteSql.append(columnName).append("=#{").append(field.getName()).append("}");
                    check = true;
                }
            }

        } catch (Exception e) {
            throw new RuntimeException("get delete sql is exceptoin:" + e);
        }
        return deleteSql.toString();
    }

    public String getById(@Param("o") Object o, @Param("temp") Class c) throws Exception {
        System.out.println("1");
        String tableName = getTableName(c);System.out.println("2");

        Field[] fields = getFields(c);System.out.println("3");
        StringBuilder selectSql = new StringBuilder();System.out.println("4");
        selectSql.append("select ");System.out.println("5");
        Field id = null;System.out.println("6");
        try {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                if (field.getAnnotation(Ignore.class) != null) {
                    continue;
                }
                if (field.getAnnotation(Id.class) != null) {
                    id = field;
                }

                String columnName = CreateCode.camelToUnderline(field.getName());
                field.setAccessible(true);

                if (i != 0) {
                    selectSql.append(",");
                }
                selectSql.append("`").append(columnName).append("`");

            }
        } catch (Exception e) {
            throw new RuntimeException("getById sql is exceptoin:" + e);
        }
        selectSql.append(" from ").append(tableName);
        if (id == null) {
            throw new RuntimeException("getById  id不能为空 需要在实体类中注解@id");
        }
        selectSql.append(" where ");
        selectSql.append(CreateCode.camelToUnderline(id.getName())).append(" = ");
        selectSql.append("#{o}");
        return selectSql.toString();

    }

    public String updateByExample(Object bean , Example example) throws Exception {
        Class<?> beanClass = bean.getClass();
        String tableName = getTableName(beanClass);
        Field[] fields = getFields(beanClass);
        StringBuilder updateSql = new StringBuilder();
        updateSql.append("update ").append(tableName).append(" set ");
        try {
            boolean check = false;
            for(int i=0;i<fields.length;i++){
                Field field=fields[i];
                if(field.getAnnotation(Ignore.class) != null){
                    continue;
                }
                String columnName = CreateCode.camelToUnderline(field.getName());
                field.setAccessible(true);
                Object beanValue = field.get(bean);

                if(beanValue!=null){
                    if(check){
                        updateSql.append(",");
                    }
                    updateSql.append(columnName).append("=#{").append(field.getName()).append("}");
                    check = true;
                }
            }
        }catch (Exception e){
            throw new RuntimeException("get update sql is exceptoin:" + e);
        }
        updateSql.append(" where ").append(example.getCondition());
        return updateSql.toString();
    }

    public String insertEntity(Object bean) throws Exception {
        Class<?> beanClass = bean.getClass();
        String tableName =getTableName(beanClass);
        Field[] fields = getFields(beanClass);
        StringBuilder insertSql =new StringBuilder();
        List<String> insertParas = new ArrayList<String>();
        List<String> insertParaNames = new ArrayList<String>();
        insertSql.append("insert into ").append(tableName).append("(");
        Field id = null;
        try {
            for(int i=0;i<fields.length;i++){
                Field field = fields[i];
                if(field.getAnnotation(Ignore.class) != null){
                    continue;
                }
                if (field.getAnnotation(Id.class) != null) {
                    id = field;
                }
                String columnName = CreateCode.camelToUnderline(field.getName());
                field.setAccessible(true);
                Object object = field.get(bean);
                if(object!=null&&(!id.getName().equals(field.getName()))){
                    insertParaNames.add(columnName);
                    insertParas.add("#{"+field.getName()+"}");
                }
            }
        }catch (Exception e){
            throw new RuntimeException("get insert sql is exceptoin:" + e);
        }
        for(int i = 0; i<insertParaNames.size();i++){
            //if(insertParaNames.get(i)!=id.getName()){
                insertSql.append(insertParaNames.get(i));
                if(i!=insertParaNames.size()-1){
                    insertSql.append(",");
                }
            //}

        }
        insertSql.append(") values (");
        for(int i = 0; i <insertParas.size();i++){
            //if(insertParas.get(i)!=id.getName()){
                insertSql.append(insertParas.get(i));
                if(i!=insertParas.size()-1){
                    insertSql.append(",");
                }
            //}

        }
        insertSql.append(")");
        return insertSql.toString();
    }




    private Field[] getFields(Class<?> beanClass) {
        Field[] beanFields = beanClass.getDeclaredFields();
        Class<?> beanSuperClass = beanClass.getSuperclass();
        Field[] beanSuperFields = beanSuperClass.getDeclaredFields();
        return ArrayUtils.addAll(beanFields, beanSuperFields);
    }

    private String getTableName(Class<?> beanClass) {
        String tableName = "";
        Table table = beanClass.getAnnotation(Table.class);
        if (table != null) {
            tableName = table.value();
        } else {
            tableName = camelToUnderline(beanClass.getSimpleName());
            tableName=tableName.substring(1);
        }
        return tableName;
    }
}
